#!/usr/bin/env python3
'''ultrasonic ranging using I2C'''  # 使用I2C通信协议进行超声波测距
'''software tools : smbus'''        # 使用smbus库操作I2C总线
'''hardware       : KS103    '''    # 硬件使用KS103超声波传感器

import smbus   # 加载smbus通信库
import time
import sys

# 初始化I2C总线设备文件 (1表示使用/dev/i2c-1设备)
bus = smbus.SMBus(1) # open /dev/i2c-1 (对应GPIO2/3物理引脚)

# I2C设备参数配置
address = 0x74                          # i2c device address (7位地址，对应十六进制0x74)
wr_cmd = [0xc9, 0xca, 0xcb, 0xcc]       # 温度测量命令列表 (不同精度对应输入寄存器的值)
precision = [0.5, 0.25, 0.125, 0.0625]  # 对应的实际精度 (单位：℃)

# # 写入寄存器的值为0xb2时，范围0-5m，为测量距离模式，以时间计算，单位us可以获得超声波返回的时间，计算时间可以获得距离 (距离=时间x声速(340m/s)/2)
# rd_cmd = 0xb2                       # range 0-5m, return flight time(us), remember divided by 2

# 便于捕获Ctrl+C中断，从而清理资源并退出
try:
    # 用户交互输入所需的精度
    print('Please input number 0~3 to select tempature measurement precision. ')
    print('0 : 0.5℃,')    # 精度最低
    print('1 : 0.25℃,')   # 一般精度
    print('2 : 0.125℃,')  # 较高精度
    print('3 : 0.0625℃,') # 最高精度
    
    # 获取用户输入并验证是否有效
    cmd_num = eval(input('Input number:'))
    if(cmd_num not in [0,1,2,3]):  # 输入值必须在0-3范围内
        print('Input error!')
        sys.exit()  # 错误的输入，退出
    
    print('precision selected:',precision[cmd_num]) # 显示用户选择的精度参数
    cmd = wr_cmd[cmd_num]                           # 获取对应输入寄存器的值
    
    # 主循环持续获取温度数据
    while True:
        # 发送温度测量命令 (寄存器0x2写入输入寄存器的值，来控制测量精度)
        bus.write_byte_data(address, 0x2, cmd)
        
        # 等待测量完成 (测量需要61ms，选择延时1秒)
        time.sleep(1) # MIN ~ 0.061（单位：秒）
        
        # 读取两个数据寄存器 (高字节存储在0x02，低字节存储在0x03)
        HighByte = bus.read_byte_data(address, 0x2) # 获取温度值的高8位
        LowByte = bus.read_byte_data(address, 0x3)  # 获取温度值的低8位
        
        # 数据合成处理 (将两个字节组合为16位整数)
        Dist = (HighByte << 8) + LowByte            # 位运算合并高低字节获得温度值
        
        # 负温度处理 (二进制补码转换)
        if(HighByte >= 0xF8):                       # 判断符号位 (当高5位全为1时是负数)
            data = data - 65536                     # 65536=2**16 (将16位数去除负号，无符号数转化为有符号负数)
      
        # 温度计算 (固定转换系数0.0625℃)
        Temp = data * 0.0625                        # 原始数据右移4位 (data/16)
        
        # 输出带符号的温度值
        print('Tempature:', Temp, '℃')

        #time.sleep(2)
        
except KeyboardInterrupt: # 处理Ctrl+C键盘中断信号
    pass

bus.close()             # 清理I2C资源
print('Range over!')    # 程序终止提示信息
